package org.jeecg.modules.coze.workflow.service.impl;

import com.alibaba.fastjson.JSONObject;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.coze.workflow.dto.CozeApiRequestDTO;
import org.jeecg.modules.coze.workflow.dto.CozeWorkflowRunDTO;
import org.jeecg.modules.coze.workflow.service.ICozeWorkflowService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

/**
 * Coze 工作流调用服务
 * 遵循 JeecgBoot Service 规范：@Service 注解、依赖注入、配置化读取、异常隔离
 */
@Service
public class CozeWorkflowService implements ICozeWorkflowService {

    // 从配置文件注入 Coze 相关参数（JeecgBoot 配置读取规范）
    @Value("${jeecg.coze.api-url}")
    private String cozeApiUrl;

    @Value("${jeecg.coze.token}")
    private String cozeToken;

    @Value("${jeecg.coze.max-retries}")
    private int maxRetries;

    @Value("${jeecg.coze.connect-timeout}")
    private int connectTimeout;

    @Value("${jeecg.coze.read-timeout}")
    private int readTimeout;

    @Value("${jeecg.coze.max-wait-time}")
    private long maxWaitTime;

    @Resource
    private RestTemplate restTemplate;  // 使用系统默认配置的 RestTemplate

    @Override
    public Result<JSONObject> runWorkflow(CozeWorkflowRunDTO dto) {
        try {
            // 1. 构造 Coze API 请求体
            CozeApiRequestDTO requestDTO = new CozeApiRequestDTO();
            requestDTO.setWorkflow_id(dto.getWorkflowId());
            requestDTO.setIs_async(false);
            
            CozeApiRequestDTO.CozeApiParametersDTO parameters = new CozeApiRequestDTO.CozeApiParametersDTO();
            parameters.setInput(dto.getInput());
            requestDTO.setParameters(parameters);

            // 2. 调用 Coze API（带重试机制）
            JSONObject response = callCozeApiWithRetry(requestDTO);
            return Result.OK(response);
        } catch (Exception e) {
            System.out.println("运行Coze工作流失败: " + e.getMessage());
            e.printStackTrace();
            return Result.error("运行失败：" + e.getMessage());
        }
    }

    /**
     * 带重试机制的 Coze API 调用（核心工具方法）
     */
    private JSONObject callCozeApiWithRetry(CozeApiRequestDTO requestDTO) {
        int attempt = 0;
        while (attempt < maxRetries) {
            attempt++;
            try {
                System.out.println("【Coze API】第" + attempt + "次调用，请求参数：" + JSONObject.toJSONString(requestDTO));
                return doCallCozeApi(requestDTO);  // 实际 HTTP 调用
            } catch (Exception e) {
                // 判断是否需要重试
                boolean shouldRetry = isRetryableException(e);
                String errorMsg = "第" + attempt + "次调用失败：" + e.getMessage();
                System.out.println("【Coze API】" + errorMsg + "，是否重试：" + shouldRetry);

                // 重试逻辑：未达最大次数 + 可重试异常
                if (shouldRetry && attempt < maxRetries) {
                    long waitTime = calculateWaitTime(attempt);  // 指数退避等待
                    System.out.println("【Coze API】等待" + waitTime + "ms后进行第" + (attempt + 1) + "次重试");
                    try {
                        Thread.sleep(waitTime);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();  // 恢复中断状态
                        throw new RuntimeException("【Coze API】重试等待被中断，停止调用", ie);
                    }
                } else {
                    // 重试耗尽或不可重试，抛出异常（由全局异常处理器捕获）
                    throw new RuntimeException("【Coze API】调用失败（重试" + attempt + "次耗尽）", e);
                }
            }
        }
        throw new RuntimeException("【Coze API】达到最大重试次数" + maxRetries + "次，调用失败");
    }

    /**
     * 实际 HTTP 调用（构造请求头、发送请求）
     */
    private JSONObject doCallCozeApi(CozeApiRequestDTO requestDTO) {
        // 1. 构造请求头（Coze API 认证 + JSON 格式）
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("Authorization", "Bearer " + cozeToken);  // Coze 认证方式（Bearer Token）

        // 2. 构造请求实体
        HttpEntity<CozeApiRequestDTO> httpEntity = new HttpEntity<>(requestDTO, headers);

        // 3. 发送 POST 请求（JeecgBoot 常用 RestTemplate 调用方式）
        ResponseEntity<String> response = restTemplate.exchange(
                cozeApiUrl,
                HttpMethod.POST,
                httpEntity,
                String.class
        );

        // 4. 响应转换为 JSONObject
        if (response.getStatusCode().is2xxSuccessful()) {
            return JSONObject.parseObject(response.getBody());
        } else {
            throw new RuntimeException("【Coze API】调用返回非200状态：" + response.getStatusCode() + "，响应体：" + response.getBody());
        }
    }

    /**
     * 判断是否为可重试异常（JeecgBoot 异常分类规范）
     */
    private boolean isRetryableException(Exception e) {
        // 1. 服务端 5xx 错误（500/502/503/504 为临时故障）
        if (e instanceof HttpServerErrorException) {
            HttpStatus status = ((HttpServerErrorException) e).getStatusCode();
            return status.is5xxServerError() 
                    && (status == HttpStatus.INTERNAL_SERVER_ERROR 
                    || status == HttpStatus.BAD_GATEWAY 
                    || status == HttpStatus.SERVICE_UNAVAILABLE 
                    || status == HttpStatus.GATEWAY_TIMEOUT);
        }
        // 2. 网络异常（连接超时、读取超时等）
        if (e instanceof ResourceAccessException) {
            return true;
        }
        // 其他异常（客户端 4xx 等）不可重试
        return false;
    }

    /**
     * 计算指数退避等待时间（避免雪崩，最大不超过配置的 maxWaitTime）
     */
    private long calculateWaitTime(int attempt) {
        long waitTime = (long) Math.pow(2, attempt - 1) * 1000;  // 1s, 2s, 4s...
        return Math.min(waitTime, maxWaitTime);  // 限制最大等待时间
    }
}